package org.oltu.oauth.authorization.server.controller;

import java.io.IOException;
import java.io.PrintWriter;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.utils.OAuthUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping(value="oauth")
public class AuthorizationController {
	
	OAuthIssuer oauthIssuerImpl;
	
	@PostConstruct
	public void init() {
		oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
	}
	
	@RequestMapping(value="/authorization", method=RequestMethod.GET)
	public void authorization(HttpServletRequest request, HttpServletResponse response) throws IOException{
		try {
			//dynamically recognize an OAuth profile based on request characteristic (params, method, content type etc.), perform validation
			OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
			
			validateRedirectionURI(oauthRequest);
			
			
			
			response.sendRedirect(handleSuccessResponse(request, oauthRequest));
			
			//if something goes wrong
		} catch(OAuthProblemException ex) {
			ex.printStackTrace();
			
			try {
				response.sendRedirect(handleProblemException(ex));
			} catch (OAuthSystemException e) {
				handleSystemException(response, e);
			}
		} catch (OAuthSystemException e) {
			e.getMessage();
			
			handleSystemException(response, e);
		}
	}
	
	
	protected void validateRedirectionURI(OAuthAuthzRequest oauthRequest) throws OAuthProblemException {
		if(StringUtils.isBlank(oauthRequest.getResponseType())) {
			throw OAuthUtils.handleOAuthProblemException("Missing response_type parameter value");
		}
		
		if(StringUtils.isBlank(oauthRequest.getClientId())) {
			throw OAuthUtils.handleOAuthProblemException("Missing client_id parameter value");
		}
		
		/*if(StringUtils.isBlank(oauthRequest.getClientSecret())) {
			throw OAuthUtils.handleOAuthProblemException("Missing client_secret parameter value");
		}*/
		
		if(StringUtils.isBlank(oauthRequest.getRedirectURI())) {
			throw OAuthUtils.handleOAuthProblemException("Missing redirect_uri parameter value");
		}
	}
	
	protected String handleSuccessResponse(HttpServletRequest request, OAuthAuthzRequest oauthRequest) throws OAuthSystemException {
		//build OAuth response
		OAuthResponse resp = OAuthASResponse
									.authorizationResponse(request, HttpServletResponse.SC_FOUND)
									.setCode(oauthIssuerImpl.authorizationCode())
									.location(oauthRequest.getRedirectURI())
									.buildQueryMessage();
		
		return resp.getLocationUri();
	}
	
	protected String handleProblemException(OAuthProblemException ex) throws OAuthSystemException {
		final OAuthResponse resp = OAuthResponse
				.errorResponse(HttpServletResponse.SC_FOUND)
				.error(ex)
				.location(ex.getRedirectUri())
				.buildQueryMessage();
		
		return resp.getLocationUri();
	}
	
	protected void handleSystemException(HttpServletResponse response, Exception ex) {
		try {
			PrintWriter writer = response.getWriter();
			writer.print(ex.getMessage());
			writer.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
